#include "config.h"
#include "str.h"
#include "pubfunc.h"
#include <iostream>
using namespace std;

ConfigImport::ConfigImport(Config &config):config(config)
{
}

int ConfigImport::importConfig(const char *filename)
{
	if (0 == filename){
		return -1;
	}
  FILE* in = fopen (filename, "r");
	if (!in){
		return -1;
	}

	unsigned int buffer_size = 4096;
	unsigned int read_pos = 0;
	char *buffer = 0;
	buffer = new char[buffer_size];
	if (!buffer){
		fclose (in);
		return -1;
	}

	string section;
	char *end = 0;

	while (fgets (buffer+read_pos, buffer_size - read_pos, in)){
		// Check if we got all the line.
		end = strrchr (buffer + read_pos, '\n'); // look for end of line
		if (!end){ // we havn't reach the end of the line yet
			// allocate a new buffer - double size the previous one
			char *temp_buffer;
			temp_buffer = new char[buffer_size * 2];
			if (!temp_buffer){
				delete [] buffer;
				fclose (in);
				return -1;
			}

			// copy the beginnning of the line
			memcpy (temp_buffer, buffer, buffer_size);
			read_pos = buffer_size - 1;
			buffer_size *= 2;
			delete [] buffer;
			buffer = temp_buffer;
			continue;
		}
		read_pos = 0;
					
		// Check for a comment
		if (buffer[0] == ';' || buffer[0] == '#'){
			continue;
		}

		if (buffer[0] == '['){
			// We have a new section here, strip out the section name
			end = strrchr (buffer, ']');
			if (!end){
				fclose (in);
				delete [] buffer;
				return -3;
			}
			*end = 0;
			
			section = buffer + 1;
			continue;
		}	// end if firs char is a [

		int rc = processLineFormat(buffer, section);
		if (rc != 0){
			fclose (in);
			delete [] buffer;
			return rc;
		}
	}				// end while fgets

  if (ferror (in)){
  	fclose (in);
		delete [] buffer;
		return -1;
	}

	fclose (in);
  delete [] buffer;
  return 0;
}

int ConfigImport::processLineFormat (char* buffer, const string & section)
{
	// Chop any cr/lf at the end of the line.
	char *endp = strpbrk (buffer, "\r\n");
	if (endp != 0){
		*endp = '\0';
	}
	
	string sign = "=";
	if (section == "mapping"){
		sign = "->";
	}
	// assume this is a value, read in the value name
	char* end = strstr (buffer, sign.c_str());
	if (end){
		*end = 0;
		end += sign.length();
		config.setSectionValues(section, buffer, end);
	}
	return 0;
}

const map<string, string>& Config::getMappingContent()
{
	map<string, map<string, string> >::iterator iter = config.find("mapping");
	if (iter == config.end()){
		return nullMappingContent;
	}
	return iter->second;
}

const string &Config::getSectionValue(const string &section, const string &name)
{
	string s, n;
		
	s = section;
	n = name;
/*	
	Str::upper(s);
	Str::upper(n);
*/	
	map<string, map<string, string> >::iterator iter = config.find(s);
	if (iter == config.end()){
		return nullString;
	}
	map<string, string>::iterator iter2 = iter->second.find(n);
	if (iter2 == iter->second.end()){
		return nullString;
	}
	return iter2->second;
}

void Config::setSectionValues(const string &section, const string &name, const string &value)
{

	string s, n;
		
	s = section;
	n = name;
/*		
	Str::upper(s);
	Str::upper(n);
*/
	if (config.find(s) == config.end()){
		map<string, string> sc;
		config[s] = sc;
	}
	config[s][n] = value;
}
